package com.usc.csci588.chaltrojan.ui.main;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;

import com.google.android.maps.*;
import com.usc.csci588.chaltrojan.R;
import com.usc.csci588.chaltrojan.location.map.CTItemizedOverlay;
import com.usc.csci588.chaltrojan.location.map.route.NavigationSaxHandler;
import com.usc.csci588.chaltrojan.location.map.route.Road;
import com.usc.csci588.chaltrojan.location.map.route.RoadProvider;
import com.usc.csci588.chaltrojan.login.Constants;
import com.usc.csci588.chaltrojan.login.EditTripActivity;
import com.usc.csci588.chaltrojan.login.UpdateTripDataActivity;
import com.usc.csci588.chaltrojan.photoupload.S3UploaderActivity;

import android.annotation.TargetApi;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.GestureDetector.OnDoubleTapListener;
import android.view.GestureDetector.OnGestureListener;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import android.view.GestureDetector;


/**
 * @author jaspreet
 *
 */
public class MainUIMapActivity extends MapActivity  implements OnGestureListener, OnDoubleTapListener {

	public static final int LONG_PRESS_THRESHOLD = 300;
	private GeoPoint lastMapCentre;//This is the last map centre
	private Timer longPressTimer = new Timer();//This is the timer for the long press hold
	private MainUIMapActivity.onLongPressListener longPressListener;//This is the long press listener

	private GestureDetector gestureDetector;

	
	String handle;
	MapView mv = null;
	MapController mc = null;
	List<Overlay> mapOverlays = null;
	
	ImageButton camera;
	ImageButton refresh;
	ImageButton navBtn;
	ImageButton bill;
	
	
	boolean menuOn;

	TextView viewTripName = null;
	
	private Boolean showResults = null;
	Location myCurrLocation = null;
	static final int HIGH_ZOOM = 17;
	static final int MED_HIGH_ZOOM = 15;
	static final int MED_ZOOM = 12;
	static final int LOW_ZOOM = 7;
    
	double latDest = 0.0;
	double lonDest = 0.0;
	
	double[] latArray;
	double[] longArray;
	String[] handlesArray;
	
	GeoPoint des = null;
	
	LinearLayout menu  = null;
	
    public Boolean getShowResults() {
		return showResults;
	}

	public void setShowResults(Boolean showResults) {
		this.showResults = showResults;
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// TODO Auto-generated method stub
			
		getMenuInflater().inflate(R.menu.map_menu, menu);
		
		//Button getNav = findViewById(R.menu.map_menu)
		
		return true;
		
	}
	
	private void navigateMe(){
		//myCurrLocation 
		try {
			GeoPoint startPoint = createGeoPoint(myCurrLocation.getLatitude(), myCurrLocation.getLongitude() );
			StringBuilder urlString = new StringBuilder("");
			urlString.append("http://maps.google.com/maps?saddr=");
	    	urlString.append(Double.toString(startPoint.getLatitudeE6()/ (double)1E6));
	    	urlString.append(",");
	    	urlString.append(Double.toString(startPoint.getLongitudeE6()/ (double)1E6));
	    	urlString.append("&daddr=");// to
	    	urlString.append(Double.toString(des.getLatitudeE6()/ (double)1E6));
	    	urlString.append(",");
	    	urlString.append(Double.toString(des.getLongitudeE6()/ (double)1E6));
			
	    	final String urlstr = urlString.toString();
	    	
	    	Log.d("nav","urlstr --> "+urlstr);
			
	        AlertDialog.Builder adb = new AlertDialog.Builder(this);
	        adb.setTitle("Chal, Trojan!");
	        	adb.setMessage("You will be redirected outside the app to view navigation instructions..");
	        adb.setPositiveButton("OK",
	        	new DialogInterface.OnClickListener(){
					@Override
					public void onClick(DialogInterface dialog, int which) {
						//We have to send this to intent
						try {
							
							Intent intent = new Intent(android.content.Intent.ACTION_VIEW, Uri.parse(urlstr));
							//intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
							startActivity(intent);			
				        } catch (ActivityNotFoundException anfe) {
				    		Toast.makeText(MainUIMapActivity.this.getApplicationContext(), "Your phone has no app for navigation..", Toast.LENGTH_LONG).show();			        	
				        }
					}

	        	}
	        );
	        adb.setNegativeButton("Cancel", null);
	        adb.show();
			
		} catch (Exception e){
			Toast.makeText(MainUIMapActivity.this.getApplicationContext(), "Unable to fetch data, there might be a problem with your internet connection..", Toast.LENGTH_LONG).show();
			Log.d("nav", e.toString());
		}
		

	}
	
	private void handleHelp(){
    	AlertDialog.Builder adb = new AlertDialog.Builder(MainUIMapActivity.this);
    	adb.setTitle(" Help");
    	adb.setMessage("Click on the map icons to view more information.. ");
    	adb.setPositiveButton("Close",null);
    	adb.show();
		
	}
	
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// TODO Auto-generated method stub
		
		switch(item.getItemId())
		{
			case R.id.findPlaces:
				break;
			case R.id.editTrip:
				startActivity(new Intent(getApplicationContext(),EditTripActivity.class));
				break;
			case R.id.clickSnaps:
				handleCameraClick(null);
				break;
			case R.id.getNav:
				navigateMe();
				break;
			case R.id.endTrip:
				finish();
				break;
			case R.id.Help:
				handleHelp();
				break;
		}
		
		return true;
	}
	
    
    private void comingFromCreateActivity(Bundle extras) {
		//destination is
    	try {
	    	latDest = extras.getDoubleArray(Constants.Lat_Lng)[0];
	    	lonDest = extras.getDoubleArray(Constants.Lat_Lng)[1];
	    	Log.d("ui","found extras: Lat = "+latDest + " Lngi: "+lonDest );
	    	updateTripName(extras.getString(Constants.TripName));
	    	Log.d("ui","found extras: TripName = "+viewTripName.getText().toString() );
	        des = createGeoPoint(latDest  , lonDest  );
    	} catch (Exception e){
    		Log.d("update",e.getMessage());
    		return;
    	}
	}

    private void comingFromUpdateActivity(Bundle extras) {
		Log.d("ui","comingFromUpdateActivity starts");
    	//destination is
    	
//    	double[] latArray;
//    	double[] longArray;
//    	String[] handlesArray;
    	
    	//List<GeoPoint> ptList = new ArrayList<GeoPoint>(handles.length);
    	try {
        	handlesArray = extras.getStringArray(Constants.HandleArray);
        	latArray = extras.getDoubleArray(Constants.latArray);
        	longArray = extras.getDoubleArray(Constants.longArray);

        	comingFromCreateActivity(extras);
        	
        	//if (handlesArray.length == 0 || latArray.length == 0 || longArray.length == 0) return;
    	
        	Log.d("update","Arrays are: handlesArray --> "+handlesArray+" latArray --> "+latArray+" longArray --> "+longArray);
        	
//	    	Log.d("ui","found extras: Lat = "+latDest + " Lngi: "+lonDest );
//	    	updateTripName(extras.getString(Constants.TripName));
//	    	//extras.get
//	        des = createGeoPoint(latDest * 1E-6 , lonDest * 1E-6 );
    	} catch (Exception e){
    		Log.d("update",e.getMessage());
    		return;
    	}
    	
	}
    
    //private void print
    
    private boolean showOtherLocations(){
    	try {
        	if (handlesArray.length == 0 || latArray.length == 0 || longArray.length == 0) return true;
    		
    		for(int i=0; i<handlesArray.length ;i++) 
    		{
	        	String uname = handlesArray[i];
	        	double lat = latArray[i];
	        	double longi= longArray[i];
	
	            GeoPoint gp = createGeoPoint(lat  , longi  ); 
				setupOverlay(mv, createGeoPointsList(gp), viewTripName.getText().toString(), Constants.makeLocationString(uname), 
						this.getResources().getDrawable(R.drawable.location_person)); 
	        	
	        	
    		}
//	    	Log.d("ui","found extras: Lat = "+latDest + " Lngi: "+lonDest );
//	    	updateTripName(extras.getString(Constants.TripName));
//	    	//extras.get
//	        des = createGeoPoint(latDest * 1E-6 , lonDest * 1E-6 );
    	} catch (Exception e){
    		return false;
    	}   	
    	return true;
    }
    
    private boolean areThereOtherLocations(){
    	try {
    		if (handlesArray.length == 0 || latArray.length == 0 || longArray.length == 0) return false;
    	} catch (Exception e) {
    		return false;
    	}
    	
    	return true;
    }
    
    public boolean onTouchEvent(MotionEvent ev) {
        if(this.gestureDetector.onTouchEvent(ev))
           return true;
        else
          return super.onTouchEvent(ev);
      }

    
	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_ui_map_view);
        menu = (LinearLayout) findViewById(R.id.menu_btn_layout);
        //menu.setVisibility(View.INVISIBLE);
        viewTripName = (TextView) findViewById(R.id.tripName);
        viewTripName.setText("Chal Trojan!!");
        menuOn = false;       
        
        Bundle extras = getIntent().getExtras();
        if(extras !=null)
        {
        	int requestingActivity = extras.getInt(Constants.mainUIRequestedFrom);
        	Log.d("maps","Requester code for main map UI activity ---> "+requestingActivity);
        	
        	//we will get the trip name as part of this bundle; we will then update the tripName being shown in view
    		//comingFromCreateActivity(extras);
        	
        	if (requestingActivity == Constants.mainUIFromCreateTrip) {
        		//we are coming createTrip do accordingly
        		comingFromCreateActivity(extras);
        	} else if(requestingActivity == Constants.mainUIFromUpdateTrip) {
        		comingFromUpdateActivity(extras);
        	}
        	
        	//String tripIsNamed = "Vegas!!";
        	//updateTripName(tripIsNamed);
        } else {
        	Log.d("maps","bundle was null ---> ");
        	updateTripName("Chal Trojan!!");
        	
        	finish();
        }
        
        navBtn = (ImageButton) findViewById(R.id.navBtn);
        bill = (ImageButton) findViewById(R.id.addBillBtn);
        camera = (ImageButton) findViewById(R.id.addPhotoBtn);
        refresh = (ImageButton) findViewById(R.id.refreshBtn);
        
        bill.setVisibility(View.INVISIBLE);
        //navBtn.setVisibility(View.INVISIBLE);

        camera.setOnClickListener(generateCameraClickListener());
        bill.setOnClickListener(generateBillClickListener());
        navBtn.setOnClickListener(generateNavigateClickListener());
        refresh.setOnClickListener(generateRefreshClickListener());
        
        Log.d("ui","Have set the trip Name to --> "+viewTripName.getText().toString());
        
        //Find requesting activity
        setShowResults(true);
        mv = (MapView) this.findViewById(R.id.map1);
        
        //mv.setOnTouchListener(generateOnTouchListener());
        
        //mv.
        
        
        //mv.setOnFocusChangeListener(generateOnFocusChangeListener());
        
        mv = (MapView) this.findViewById(R.id.map1);
        mv.setBuiltInZoomControls(true);
        mapOverlays = mv.getOverlays();

        mv.setSatellite(false);
        mv.setClickable(true);
        //mv.setst
        
        mc = mv.getController();
		mc.setZoom(LOW_ZOOM);
        
        LocationManager lm = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
        LocationListener ll = new LocationListener() {

			/**
			 * Most useful method - called whenever GPS changes location
			 * The center point is set to the new location whenever that happens
			 */
			@Override
			public void onLocationChanged(Location point) {
				//Log.d("maps","getShowResults() = "+getShowResults());
				myCurrLocation = point;
				if (getShowResults()) {
					return;
				}

								
				Log.d("maps","location changed - It is now "+
						point.getLatitude()+ " "+point.getLongitude());
				
			       GeoPoint p = createGeoPoint(myCurrLocation.getLatitude(), myCurrLocation.getLongitude() ); 
			       mapOverlays.clear();
			       //setupOverlay(mv, createGeoPointsList(p,des));       
			       //setupOverlay(mv, p);
			       
			       setupOverlay(mv, createGeoPointsList(p), viewTripName.getText().toString(), Constants.YourLocationMsg, MainUIMapActivity.this.getResources().getDrawable(R.drawable.location_person));
			       mc.animateTo(p); 

			       if (des != null) {
			    	   setupOverlay(mv, createGeoPointsList(des),viewTripName.getText().toString(), Constants.DestinationMsg, MainUIMapActivity.this.getResources().getDrawable(R.drawable.dest_icon));
			    	   Log.d("maps","location des is : "+
								des.toString());
			    	   //mc.animateTo(des); 
			       }
			       
					Log.d("maps","myCurrLocation is Lat: "+
							myCurrLocation.toString() );
					Log.d("maps","location p is : "+
									p.toString() );		
					
					
					if(areThereOtherLocations()) {
						showOtherLocations();
					}

					mc.setZoom(LOW_ZOOM);
					
//				mapOverlays.clear();
//				GeoPoint p =  createGeoPoint(point.getLatitude() , point.getLongitude() );
//				if (!getShowResults()) {
//					mc.animateTo(p);
//					mc.setZoom(MED_HIGH_ZOOM);
//				}
//				
//				if (des!= null) {
//					setupOverlay(mv, createGeoPointsList(p,des)); 
//				} else {
//					setupOverlay(mv, p);
//				}
				
				Log.d("updateLocation","I am about to update the location.");
				
				
				SendLocationUpdate slu = new SendLocationUpdate(point.getLatitude(),point.getLongitude());
				slu.execute(handle);				
				Log.d("updateLocation","I called the constructor and now I am done.");
				
				Toast.makeText(getApplicationContext(), "Your location was updated..", Toast.LENGTH_LONG).show();
				
				Toast.makeText(getApplicationContext(), "Select navigation option to view route to destination from your  location..", Toast.LENGTH_LONG).show();

				/**
				 * This is for testing if we can show two points simultaneously
				 * //TODO - Remove after testing 
				 */

				/*
				List<GeoPoint> otherPoints = getOtherLocations(p);
				setupOverlay(mv, otherPoints);
		        //*/
				
				mv.invalidate();
				
			}

			@Override
			public void onProviderDisabled(String provider) {
				// TODO Auto-generated method stub
				
			}

			@Override
			public void onProviderEnabled(String provider) {
				// TODO Auto-generated method stub
				
			}

			@Override
			public void onStatusChanged(String provider, int status,
					Bundle extras) {
				// TODO Auto-generated method stub
			}
        	
        };
        
        /**
         * http://developer.android.com/guide/topics/location/strategies.html
         */
        lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10, 50, ll);
       
        myCurrLocation = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
        

        if (myCurrLocation == null) {
        	
        	myCurrLocation = lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
        	if (myCurrLocation == null) {
	        	myCurrLocation = new Location("");
	        	myCurrLocation.setLatitude(34.0);
	        	myCurrLocation.setLongitude(-118.0);
        	}
        }
        
       GeoPoint p = createGeoPoint(myCurrLocation.getLatitude(), myCurrLocation.getLongitude() ); 
       mapOverlays.clear();
       //setupOverlay(mv, createGeoPointsList(p,des));       
       //setupOverlay(mv, p);
       
       setupOverlay(mv, createGeoPointsList(p), viewTripName.getText().toString(), Constants.YourLocationMsg, this.getResources().getDrawable(R.drawable.location_person));
       mc.animateTo(p); 

       if (des != null) {
    	   setupOverlay(mv, createGeoPointsList(des),viewTripName.getText().toString(), Constants.DestinationMsg, this.getResources().getDrawable(R.drawable.dest_icon));
    	   Log.d("maps","location des is : "+
					des.toString());
    	   //mc.animateTo(des); 
       }
       
		Log.d("maps","myCurrLocation is Lat: "+
				myCurrLocation.toString() );
		Log.d("maps","location p is : "+
						p.toString() );		
		
		
		if(areThereOtherLocations()) {
			showOtherLocations();
		}

		Toast.makeText(getApplicationContext(), "Select navigation option to route instructions to destination from your new location..", Toast.LENGTH_LONG).show();

		
       /**
        * This is for testing if we can show two points simultaneously
        * //TODO - Remove after testing 
        */
       
       /*
			GeoPoint p2 = new GeoPoint(
            (int) (intialLocation.getLatitude() * 1.00001 * 1e6), 
            (int) (intialLocation.getLongitude() * 1.00031 * 1e6) );
       		setupOverlay(mv, p2);

        //*/
       
        //TODO
        //mc.animateTo(des);        
               
        mv.invalidate();
        

   }

	private View.OnClickListener generateCameraClickListener(){
		return new View.OnClickListener(){

			@Override
			public void onClick(View v) {
				Log.d("uibtns","generateCameraClickListener()");
				handleCameraClick(v);
			}
			
		};
	}

	private void handleCameraClick(View v){
		Intent i = new Intent(getApplicationContext(),S3UploaderActivity.class);	            
        startActivity(i);		
	}
	
	private View.OnClickListener generateBillClickListener(){
		return new View.OnClickListener(){

			@Override
			public void onClick(View v) {
				Log.d("uibtns","generateBillClickListener()");
				handleBillClick(v);
			}
			
		};	
	}
	
	private void handleBillClick(View v){
	}
	
	
	private View.OnClickListener generateRefreshClickListener(){
		return new View.OnClickListener(){

			@Override
			public void onClick(View v) {
				Log.d("uibtns","generateRefreshClickListener()");
				handleRefreshClick(v);
			}
			
		};	
	}

	private void handleRefreshClick(View v){
		// update the values from the server.
		// you need following values:
		// all users location.
		String tripName = viewTripName.getText().toString();		
		String req = generateUpdateRequest(tripName, handle);
		GetUpdatesOfTrip gut = new GetUpdatesOfTrip();
		gut.execute(req);		
	
	}

	private void updateTripNameAndDest(){
		try {
	       GeoPoint p = createGeoPoint(myCurrLocation.getLatitude(), myCurrLocation.getLongitude() ); 
	       mapOverlays.clear();
	       //setupOverlay(mv, createGeoPointsList(p,des));       
	       //setupOverlay(mv, p);
	       
	       setupOverlay(mv, createGeoPointsList(p), viewTripName.getText().toString(), Constants.YourLocationMsg, MainUIMapActivity.this.getResources().getDrawable(R.drawable.location_person));
	       mc.animateTo(p); 

	       if (des != null) {
	    	   setupOverlay(mv, createGeoPointsList(des),viewTripName.getText().toString(), Constants.DestinationMsg, MainUIMapActivity.this.getResources().getDrawable(R.drawable.dest_icon));
	    	   Log.d("maps","location des is : "+
						des.toString());
	    	   //mc.animateTo(des); 
	       }
	       
			Log.d("maps","myCurrLocation is Lat: "+
					myCurrLocation.toString() );
			Log.d("maps","location p is : "+
							p.toString() );		
			
			
			if(areThereOtherLocations()) {
				showOtherLocations();
			}

			mc.setZoom(LOW_ZOOM);
		} catch (Exception e){
			Log.d("update",e.getMessage());
		}
	}

	private View.OnClickListener generateNavigateClickListener(){
		return new View.OnClickListener(){

			@Override
			public void onClick(View v) {
				Log.d("uibtns","generateNavigateClickListener()");
				handleNavigateClick(v);
			}
			
		};	
		
	}
	
	private void handleNavigateClick(View v){
		navigateMe();
	}	

	
	private void updateTripName(String tripIsNamed) {
    	viewTripName.setText(tripIsNamed.trim());		
	}

	private GeoPoint createGeoPoint(double latitude, double longitude){
    	return new GeoPoint( (int) (latitude * 1E6 ),
				(int) (longitude * 1E6) );
    }
    
	
	private List<GeoPoint> createGeoPointsList(GeoPoint... data ){
		List<GeoPoint> newList = new ArrayList<GeoPoint>(data.length);
 
		for (GeoPoint p : data ) {
			newList.add(p); 
			Log.d("Geopoint-List","Adding point -->  "+p.toString());
		}
		
		return newList;
	}
  
    @Override
    protected void onActivityResult(int requestCode,
                                    int resultCode, Intent data) {
    	//use a switch statement for more than one request code check
    	super.onActivityResult(requestCode, resultCode, data);
    }
    
    /**
     * This is for search button, we click on it and we find out the 
     * route that we ought to take
     * @return
     */
    private View.OnFocusChangeListener generateOnFocusChangeListener(){
    	return new View.OnFocusChangeListener() {
			@Override
			public void onFocusChange(View v, boolean hasFocus) {				
				Log.d("ui","maps on focus change has focus --> "+hasFocus);
 				if (hasFocus) {
					//we need to display the layout containing buttons
					menu.setVisibility(View.VISIBLE);
				} else {
					menu.setVisibility(View.INVISIBLE);					
				}
			}

    	};
    }
 
    /**
     * This is for search button, we click on it and we find out the 
     * route that we ought to take
     * @return
     */
    private View.OnTouchListener generateOnTouchListener(){
    	return new View.OnTouchListener() {
			@Override
			public boolean onTouch(View v, MotionEvent event) {
		    	Log.d("ui","onTouch");
				handleLongPress(event);
//				return super. (v, event);
//		        int Action = event.getAction();
//				Log.d("maps","generateOnTouchListener");
//				if ( Action == MotionEvent.AXIS_PRESSURE ) {//.ACTION_UP
//					menu.setVisibility(View.VISIBLE);
//				}
				return true;
			}
			
    	};
    }
    
	public interface onLongPressListener{
		public void onLongPress(MapView mapView, GeoPoint longPressLocation);
	}
    
	public void setOnLongPressListener(MainUIMapActivity.onLongPressListener longPressListener){
		this.longPressListener = longPressListener;
	}
    
    private void handleLongPress(final MotionEvent motionEvent){
    	/*
    	 * This is the user pressing down on the
    	 * screen
    	 */
    	Log.d("ui","handleLongPress");
    	if(motionEvent.getAction() == MotionEvent.ACTION_DOWN)
    	{
    		longPressTimer = new Timer();
    		longPressTimer.schedule(new TimerTask() {

    			@Override
    			public void run() {
    				GeoPoint longPressLocation = mv.getProjection().fromPixels((int)motionEvent.getX(), (int)motionEvent.getY());
    				Log.d("ui","longPressLocation --> "+longPressLocation);
    				longPressListener.onLongPress(mv, longPressLocation);
    			}
    		}, LONG_PRESS_THRESHOLD);
    		lastMapCentre = mv.getMapCenter();
    	}
    	/*
    	 * This is the user moving their finger
    	 * on the screen
    	 */
    	if(motionEvent.getAction() == MotionEvent.ACTION_MOVE)
    	{
    		if(!mv.getMapCenter().equals(lastMapCentre))
    		{
    			longPressTimer.cancel();
    		}
    		lastMapCentre = mv.getMapCenter();
    	}
    	/*
    	 * This is the user lifting their
    	 * finger off the screen
    	 */
    	if(motionEvent.getAction() == MotionEvent.ACTION_UP)
    	{
    		longPressTimer.cancel();
    	}
    	/*
    	 * This is the case when the user has more than one
    	 * finger on the screen
    	 */
    	if(motionEvent.getPointerCount() > 1)
    	{
    		longPressTimer.cancel();
    	}
    }
    
    
    /**
     * All overlay elements on a map are held by the MapView, so when you want to add some, 
     * you have to get a list from the getOverlays() method.
     * Then instantiate the Drawable used for the map marker, which was saved 
     * in the res/drawable/ directory. 
     * @param mapView
     */

    private void setupOverlay(MapView mapView, OverlayItem overlayitem){
    	Drawable drawable = this.getResources().getDrawable(R.drawable.map_marker);
    	CTItemizedOverlay itemizedoverlay = new CTItemizedOverlay(drawable, this);
    	itemizedoverlay.addOverlay(overlayitem);

    	mapOverlays.add(itemizedoverlay);
    }
    
    private void setupOverlay(MapView mapView, GeoPoint p){
        //OverlayItem overlayitem = new OverlayItem(p, "Here, you are!!", "I'm here!");
        OverlayItem overlayitem = new OverlayItem(p, null, null);
        setupOverlay(mapView, overlayitem);
    } 
    
    private void setupOverlay(MapView mapView, OverlayItem... overlayitems){
    	Drawable drawable = this.getResources().getDrawable(R.drawable.map_marker);
    	setupOverlay(mapView, drawable, overlayitems);
    	
    	/*
    	CTItemizedOverlay itemizedoverlay = new CTItemizedOverlay(drawable, this);

    	for (OverlayItem overlayitem : overlayitems) {
        	itemizedoverlay.addOverlay(overlayitem);
        	mapOverlays.add(itemizedoverlay);    		
    	}
    	*/
    }
    
   
    private void setupOverlay(MapView mapView, Drawable d, OverlayItem... overlayitems){
    	CTItemizedOverlay itemizedoverlay = new CTItemizedOverlay(d, this);

    	for (OverlayItem overlayitem : overlayitems) {
        	itemizedoverlay.addOverlay(overlayitem);
        	mapOverlays.add(itemizedoverlay);  
        	Log.d("overlay","Adding to overlay --> "+itemizedoverlay.toString() );
    	}
    }    
    
    private void setupOverlay(MapView mapView, List<GeoPoint> points){
    	OverlayItem overlayitems[] = new OverlayItem[points.size()];
    	for (int i=0; i< points.size(); i++) {
    		overlayitems[i] = new OverlayItem(points.get(i), null, null);
    	}
        setupOverlay(mapView, overlayitems);
    }    
   
    private void setupOverlay(MapView mapView, List<GeoPoint> points, String tripName, String info){
    	OverlayItem overlayitems[] = new OverlayItem[points.size()];
    	for (int i=0; i< points.size(); i++) {
    		overlayitems[i] = new OverlayItem(points.get(i), tripName, info);
    	}
        setupOverlay(mapView, overlayitems);
    }    
     
    private void setupOverlay(MapView mapView, List<GeoPoint> points, String tripName, String info, Drawable d){
    	OverlayItem overlayitems[] = new OverlayItem[points.size()];
    	for (int i=0; i< points.size(); i++) {
    		overlayitems[i] = new OverlayItem(points.get(i), tripName, info);
    	}
        setupOverlay(mapView, d, overlayitems);
    }    
   
    private void setupOverlay(MapView mapView, List<GeoPoint> points, Drawable d){
    	OverlayItem overlayitems[] = new OverlayItem[points.size()];
    	for (int i=0; i< points.size(); i++) {
    		overlayitems[i] = new OverlayItem(points.get(i), null, null);
    	}
        setupOverlay(mapView, d, overlayitems);
    }    
     
    private void setupOverlay(MapView mapView, List<GeoPoint> points, Drawable d, String tripName, String info){
    	OverlayItem overlayitems[] = new OverlayItem[points.size()];
    	for (int i=0; i< points.size(); i++) {
    		overlayitems[i] = new OverlayItem(points.get(i), tripName, info);
    	}
        setupOverlay(mapView, d, overlayitems);
    }    
    
    
    
    /**
     * This function will get points of friends to be obtained from server
     * @param p - this person's pointer
     */
    private List<GeoPoint> getOtherLocations(GeoPoint p){
    	List<GeoPoint> points = new ArrayList<GeoPoint>();
    	/**
    	 * current dummy point generator
    	 */
    	
    	points.add(new GeoPoint( (int) (p.getLatitudeE6()*1.00011), (int) (p.getLongitudeE6()*1.00011)) );
    	points.add(new GeoPoint( (int) (p.getLatitudeE6()*1.00031), (int) (p.getLongitudeE6()*1.0002)) );
    	
    	return points;
    }
    
    

    @Override
    protected boolean isRouteDisplayed() {
    	return false;
    }

	@TargetApi(8)
	protected void displayRoute(final double fromLat, final double fromLon,
			final double toLat, final double toLon) throws IOException, SAXException, ParserConfigurationException, JSONException {
		
		String urlString = RoadProvider.getUrl(fromLat, fromLon, toLat, toLon);


		HttpPost httppost = new HttpPost(urlString);
		HttpClient httpclient = new DefaultHttpClient();
		HttpResponse response = httpclient.execute(httppost);
		HttpEntity entity = response.getEntity();
		InputStream is = null;
		is = entity.getContent();
		
		BufferedReader reader = new BufferedReader(new InputStreamReader(is, "iso-8859-1"), 8);
		StringBuilder sb = new StringBuilder();
		sb.append(reader.readLine() + "\n");
		String line = "0";
		while ((line = reader.readLine()) != null) {
		    sb.append(line + "\n");
		}
		is.close();
		reader.close();
		String result = sb.toString();
		
		JSONObject jsonObject = new JSONObject(result);
		JSONArray routeArray = jsonObject.getJSONArray("routes");
		JSONObject routes = routeArray.getJSONObject(0);
		JSONObject overviewPolylines = routes.getJSONObject("overview_polyline");
		String encodedString = overviewPolylines.getString("points");
		List<GeoPoint> pointToDraw = decodePoly(encodedString);

		GeoPoint p = createGeoPoint(myCurrLocation.getLatitude() , myCurrLocation.getLongitude() ); 
	   	mapOverlays.clear();
		setupOverlay(mv, p);       

		Drawable drawable = getResources().getDrawable(R.drawable.map_marker_plot);
		setupOverlay(mv, pointToDraw, drawable);
//		mc.animateTo(pointToDraw.get(0));
		mc.setZoom(LOW_ZOOM);
		
		//Toast.makeText(getApplicationContext(), "Total overlays = "+ mapOverlays.size() , Toast.LENGTH_LONG).show();

		mv.invalidate();
		
        // create the factory
        SAXParserFactory factory = SAXParserFactory.newInstance();
        // create a parser
        SAXParser parser = factory.newSAXParser();
        // create the reader (scanner)
        XMLReader xmlreader = parser.getXMLReader();
        // instantiate our handler
        NavigationSaxHandler navSaxHandler = new NavigationSaxHandler();
        // assign our handler
        xmlreader.setContentHandler(navSaxHandler);
        // get our data via the url class
        
		Log.d("maps","urlString is "+urlString);
		
		/*
		Runnable r  = new Runnable(){
			   @Override
			   public void run() {
				   String kmlString;
				try {
					kmlString = convertStreamToString(url.openStream());
					Log.d("maps","stream is "+kmlString); 
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			   }
		};
		handler.post(r);
		*/
		
//		StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); 
//		StrictMode.setThreadPolicy(policy); 
//		
//		
//		String kmlString = convertStreamToString(url.openStream());
//		Log.d("maps","stream is "+kmlString); 
//        
//        InputSource is = new InputSource(url.openStream());
//        xmlreader.parse(is);

        
		/*

        
        // perform the synchronous parse           
        // get the results - should be a fully populated RSSFeed instance, or null on error
        
        NavigationDataSet ds = navSaxHandler.getParsedData();
        drawPath(ds, Color.parseColor("#add331"), mv );

		//*/
        
		/*
		new Thread() {
			@Override
			public void run() {
				double fromLat = 49.85, fromLon = 24.016667, toLat = 50.45, toLon = 30.523333;
				String url = RoadProvider.getUrl(fromLat, fromLon, toLat, toLon);
				InputStream is = getConnection(url);
				
				//Testing xml
								
				//String xml = convertStreamToString(is);
				//Log.d("maps", xml);
				//System.err.println(xml);
				
				mRoad = RoadProvider.getRoute(is);
				if (mRoad == null) {
					Log.d("maps", "mRoad == null");
				}
				mHandler.sendEmptyMessage(0);
			}
		}.start();
		//*/
	}

	
	/*
    Handler mHandler = new Handler() {
        public void handleMessage(android.os.Message msg) {
	        	AlertDialog.Builder adb = new AlertDialog.Builder(MainUIMapActivity.this);
	        	adb.setTitle("Chal, Trojan!");
	        	adb.setMessage(mRoad.mName + " " + mRoad.mDescription);
	        	adb.setPositiveButton("Close",null);
	        	adb.show();

                RoadRouteOverlay mapOverlay = new RoadRouteOverlay(mRoad, mv);
                List<Overlay> listOfOverlays = mv.getOverlays();
                listOfOverlays.clear();
                listOfOverlays.add(mapOverlay);
                mv.invalidate();
        };
    };
    //*/

    static public String convertStreamToString(InputStream is) { 
    	   try {
    	        return new java.util.Scanner(is).useDelimiter("\\A").next();
    	    } catch (java.util.NoSuchElementException e) {
    	        return "";
    	    }
    }

    private List<GeoPoint> decodePoly(String encoded) {

        List<GeoPoint> poly = new ArrayList<GeoPoint>();
        int index = 0, len = encoded.length();
        int lat = 0, lng = 0;

        while (index < len) {
            int b, shift = 0, result = 0;
            do {
                b = encoded.charAt(index++) - 63;
                result |= (b & 0x1f) << shift;
                shift += 5;
            } while (b >= 0x20);
            int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
            lat += dlat;

            shift = 0;
            result = 0;
            do {
                b = encoded.charAt(index++) - 63;
                result |= (b & 0x1f) << shift;
                shift += 5;
            } while (b >= 0x20);
            int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
            lng += dlng;

            GeoPoint p = new GeoPoint((int) (((double) lat / 1E5) * 1E6), (int) (((double) lng / 1E5) * 1E6));
            poly.add(p);
        }

        return poly;
    }

	@Override
	public boolean onDoubleTap(MotionEvent e) {
		Log.d("ui","Inside onDoubleTap ");
		GeoPoint p = mv.getProjection().fromPixels((int)e.getX(), (int)e.getY());
		Log.d("ui","onDoubleTap(MotionEvent e)");
	    AlertDialog.Builder dialog = new AlertDialog.Builder(this);
	    dialog.setTitle("Double Tap");
	    dialog.setMessage("Location: " + p.getLatitudeE6() + ", " + p.getLongitudeE6());
	    dialog.show();	
		
	    if (!menuOn) {
	    	menuOn = true;
	    } else {
	    	menuOn = false;
	    }
	    
	    if(menuOn){
	    	//show the menu
	    }
	    
	    
		return true;
	}

	@Override
	public boolean onDoubleTapEvent(MotionEvent e) {
		Log.d("ui","onDoubleTapEvent");
		return true;
	}

	@Override
	public boolean onSingleTapConfirmed(MotionEvent e) {
		// TODO Auto-generated method stub
		Log.d("ui","onSingleTapConfirmed");
		return true;
	}

	@Override
	public boolean onDown(MotionEvent e) {
		// TODO Auto-generated method stub
		Log.d("ui","onDown");
		return true;
	}

	@Override
	public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
			float velocityY) {
		// TODO Auto-generated method stub
		Log.d("ui","onFling");
		return true;
	}

	@Override
	public void onLongPress(MotionEvent e) {
		// TODO Auto-generated method stub
		Log.d("ui","onLongPress");
		
	}

	@Override
	public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
			float distanceY) {
		// TODO Auto-generated method stub
		Log.d("ui","onScroll");
		return true;
	}

	@Override
	public void onShowPress(MotionEvent e) {
		// TODO Auto-generated method stub
		Log.d("ui","onShowPress");
	}

	@Override
	public boolean onSingleTapUp(MotionEvent e) {
		// TODO Auto-generated method stub
		Log.d("ui","onSingleTapUp");
		return true;
	}
	
	public String generateUpdateRequest(String tn, String handle) {
		// http://ec2-23-22-128-131.compute-1.amazonaws.com:8080/ChalTrojan2/GetLocation?tripId=28
		String updateURL = Constants.ChalTrojanHostName;
		updateURL += "/ChalTrojan2/GetLocation?tripId=" + tn;
		updateURL += "&handle=" + handle;
		Log.d("update", "updateURL is --> " + updateURL);
		return updateURL;
	}
	
	
	private class GetUpdatesOfTrip extends AsyncTask<String, Void, Void> {

		ProgressDialog pd;

		@Override
		protected void onPreExecute() {
			// TODO Auto-generated method stub
			super.onPreExecute();
			pd = ProgressDialog.show(MainUIMapActivity.this,
					"Member Information",
					"Fetching member information from the server...");

		}

		@Override
		protected Void doInBackground(String... params) {
			// TODO Auto-generated method stub

			String request = params[0];
			try {

				DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory
						.newInstance();
				DocumentBuilder documentBuilder = documentBuilderFactory
						.newDocumentBuilder();
				Document document = documentBuilder.parse(request);
				Log.d("join", "Got here.");
				NodeList locationList = document.getElementsByTagName("location");
				int len = locationList.getLength();
				Log.d("join", "Location Length is " + len);
				Log.d("join", locationList.toString());				
				/*
				double[] latArray;
				double[] longArray;
				String[] handlesArray;
				*/
				if(len == 0)
				{
				handlesArray = null;
				latArray = null;
				longArray = null;					
				}
				else
				{
				handlesArray = new String[len];
				latArray = new double[len];
				longArray = new double[len];
				
				}				
				for (int i = 0; i < len; i++) {

					Node node = locationList.item(i);
					Element locationElement = (Element) node;

					NodeList handleList = locationElement
							.getElementsByTagName("handle");
					NodeList latList = locationElement
							.getElementsByTagName("lat");
					NodeList longList = locationElement
							.getElementsByTagName("long");

					Node handle = handleList.item(0);
					Node lat = latList.item(0);
					Node lng = longList.item(0);

					handlesArray[i] = handle.getTextContent();
					latArray[i] = Double.parseDouble(lat.getTextContent());
					longArray[i] = Double.parseDouble(lng.getTextContent());

					// Log.d("join",handles[i]+" "+lats[i]+","+ lngs[i]);

				}

				 
			} catch (ParserConfigurationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (SAXException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			return null;

		}

		@Override
		protected void onPostExecute(Void result) {
			// TODO Auto-generated method stub
			super.onPostExecute(result);
			pd.dismiss();
			updateTripNameAndDest();
			if(areThereOtherLocations())
			{
				showOtherLocations();
			}

		}

	}

	
	
	
	
	
    
}

class RoadRouteOverlay extends com.google.android.maps.Overlay {
    Road mRoad;
    ArrayList<GeoPoint> mPoints;

    public RoadRouteOverlay(Road road, MapView mv) {
            mRoad = road;
            if (road.mRoute.length > 0) {
                    mPoints = new ArrayList<GeoPoint>();
                    for (int i = 0; i < road.mRoute.length; i++) {
                            mPoints.add(new GeoPoint((int) (road.mRoute[i][1] * 1000000),
                                            (int) (road.mRoute[i][0] * 1000000)));
                    }
                    int moveToLat = (mPoints.get(0).getLatitudeE6() + (mPoints.get(
                                    mPoints.size() - 1).getLatitudeE6() - mPoints.get(0)
                                    .getLatitudeE6()) / 2);
                    int moveToLong = (mPoints.get(0).getLongitudeE6() + (mPoints.get(
                                    mPoints.size() - 1).getLongitudeE6() - mPoints.get(0)
                                    .getLongitudeE6()) / 2);
                    GeoPoint moveTo = new GeoPoint(moveToLat, moveToLong);

                    MapController mapController = mv.getController();
                    mapController.animateTo(moveTo);
                    mapController.setZoom(MainUIMapActivity.LOW_ZOOM);
            }
            Log.d("maps", "road.mRoute.length = "+road.mRoute.length);
            
    }

    @Override
    public boolean draw(Canvas canvas, MapView mv, boolean shadow, long when) {
        Log.d("maps", "mPoints.size() = "+mPoints.size());
            super.draw(canvas, mv, shadow);
            drawPath(mv, canvas);
            return true;
    }

    public void drawPath(MapView mv, Canvas canvas) {
            int x1 = -1, y1 = -1, x2 = -1, y2 = -1;
            Paint paint = new Paint();
            paint.setColor(Color.GREEN);
            paint.setStyle(Paint.Style.STROKE);
            paint.setStrokeWidth(3);
            for (int i = 0; i < mPoints.size(); i++) {
                    Point point = new Point();
                    mv.getProjection().toPixels(mPoints.get(i), point);
                    x2 = point.x;
                    y2 = point.y;
                    if (i > 0) {
                            canvas.drawLine(x1, y1, x2, y2, paint);
                    }
                    x1 = x2;
                    y1 = y2;
            }
    }
}

/*




*/